package cn.chendd.example.jpa.nativequery.enums;

import cn.chendd.example.jpa.nativequery.annotions.Column;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.hibernate.type.Type;

import java.lang.reflect.Field;
import java.util.Map;

/**
 * 查询字段的范围
 * @author chendd
 * @date 2020/5/6
 */
public enum QueryColumnScope implements IQueryColumnScope{

    //全部属性
    All(){
        public Map<String , ? extends Type> getColumnType(Class<?> mappingClass, String[] filter) {
            Map<String, Type> dataMap = Maps.newLinkedHashMap();
            for (; mappingClass != Object.class; mappingClass = mappingClass.getSuperclass()) {
                Field[] fields = mappingClass.getDeclaredFields();
                for (Field field : fields) {
                    Column column = field.getAnnotation(Column.class);
                    if(column == null){
                        continue;
                    }
                    String name = column.name();
                    String key = StringUtils.isEmpty(name) ? field.getName() : name;
                    dataMap.put(key , this.convertColumnType(column.type() , field.getType()));
                }
            }
            return dataMap;
        }
    },
    //包含属性
    Include{
        @Override
        public Map<String, ? extends Type> getColumnType(Class<?> mappingClass, String[] include) {
            Map<String , ? extends Type> dataMap = QueryColumnScope.All.getColumnType(mappingClass , include);
            if(include.length > 0){
                Map<String , Type> newMap = Maps.newLinkedHashMap();
                for (String prop : include) {
                    newMap.put(prop , dataMap.get(prop));
                }
                return newMap;
            }
            return dataMap;
        }
    },
    ;

    public static Map<String, ? extends Type> getColumnMapping(Class<?> mappingClass, String[] include) {

       return QueryColumnScope.Include.getColumnType(mappingClass , include);
    }

    protected Type convertColumnType(Class<? extends Type> columnType, Class<?> fieldType) {
        if(columnType == Type.class){
            //按照默认当前属性类型 + Type为映射类型进行转换
            String className = "org.hibernate.type." + fieldType.getSimpleName() + "Type";
            try {
                return (Type) FieldUtils.readDeclaredStaticField(Class.forName(className) , "INSTANCE");
            } catch (IllegalAccessException | ClassNotFoundException e) {
                throw new IllegalStateException(e);
            }
        } else {
            //按照传递的类型进行转换
            try {
                return (Type) FieldUtils.readDeclaredStaticField(columnType , "INSTANCE");
            } catch (IllegalAccessException e) {
                throw new IllegalStateException(e);
            }
        }
    }

}

interface IQueryColumnScope {

    Map<String , ? extends Type> getColumnType(Class<?> mappingClass, String include[]);

}